package func;
import java.util.*;

import point.*;
import node.Node;

public class GameRankFunction implements RankFunction {
	
	private Node[] pop;
	private int size;
	
	public GameRankFunction(int boardSize) {
		Point.setSize(boardSize);
		size = boardSize;
	}

	public void sortByRank(Node[] pop) {
		this.pop = pop;
		
		Comparator<Node> comp = new
			Comparator<Node>() {
				public int compare(Node n1, Node n2) {
					return applyScoreFunction(n1) - applyScoreFunction(n2);
				}
			};
		
		Arrays.sort(pop, comp);
	}
	
	/**
	 * @PRECONDITION sortByRank must be called first with a valid array. The node
	 * which is passed as the parameter in applyScoreFunction must be in the array.
	 * */
	public int applyScoreFunction(Node n) {
		if(pop == null)
			return 0;
		
		int loses = 0;
		for(Node node : pop) {
			if(node == n)
				continue;
			
			int winner = gridGame(new Node[]{n, node});
			switch(winner) {
			case -1:
				loses = loses + 1;
				break;
			case 1:
				loses = loses + 2;
				break;
			}
		}
		
		for(Node node : pop) {
			if(node == n)
				continue;
			
			int winner = gridGame(new Node[]{node, n});
			switch(winner) {
			case -1:
				loses = loses + 1;
				break;
			case 0:
				loses = loses + 2;
				break;
			}
		}
		
		return loses;
	}
	
	public int gridGame(Node[] players) {
		Random ran = new Random();		
		int[] lastMove = {-1, -1};
		int d = size / 2;
		Point player1 = new Point(ran.nextInt(size), ran.nextInt(size));
		Point[] location = {player1, new Point((player1.getRow() + d) % size, 
				(player1.getColumn() + d) % size)};
		
		for(int j = 0; j < 50; j++) {
			for(int i = 0; i < 2; i++) {
				int[] locs = {location[i].getRow(), location[i].getColumn(),
						location[1 - i].getRow(), location[1 - i].getColumn(), lastMove[i]};
				
				int move = posRem(players[i].evaluate(locs) % 4);
				if(move == lastMove[i])
					return 1 - i;
				
				lastMove[i] = move;
				switch(move) {
				case 0:
					location[i].north();
					break;
				case 1:
					location[i].south();
					break;
				case 2:
					location[i].west();
					break;
				case 3:
					location[i].east();
					break;
				}
				
				if(location[i].equals(location[1 - i]))
					return i;
			}
		}
		
		return -1;
	}
	
	private int posRem(int k) {
		if(k < 0)
			return k + 4;
		else
			return k;
	}
}
